package afcepf.atod18.frameworkMVC2.in_memory_compile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.tools.JavaCompiler;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.ToolProvider;

import org.apache.log4j.Logger;

public class CompileJavaSource {

    private static final CompileJavaSource INSTANCE = new CompileJavaSource();

    private static final Logger logger = Logger.getLogger(CompileJavaSource.class);

    private CompileJavaSource() {
    }

    public static CompileJavaSource getInstance() {
        return INSTANCE;
    }

    public static Class<?> Compile(String sourceFilename, String sourceLines)
            throws IOException {
        // String sourceFilename;
        //    Full name of the class that will be compiled.
        //    If class should be in some package,
        //    fullName should contain it too
        //    (ex. "testpackage.DynaClass")
 
        logger.info("Source Code to compile:");
        logger.info("---------------------------------------------------");
        logger.info(sourceLines);
        logger.info("---------------------------------------------------");

        // We get an instance of JavaCompiler. Then
        // we create a file manager
        // (our custom implementation of it)
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        JavaFileManager fileManager = new ClassFileManager(
                compiler.getStandardFileManager(null, null, null));

        // Dynamic compiling requires specifying
        // a list of "files" to compile. In our case
        // this is a list containing one "file" which is in our case
        // our own implementation (see details below)
        List<JavaFileObject> jfiles = new ArrayList<JavaFileObject>();
        jfiles.add(new CharSequenceJavaFileObject(sourceFilename, sourceLines));

        // We specify a task to the compiler. Compiler should use our file
        // manager and our list of "files".
        // Then we run the compilation with call()
        compiler.getTask(null, fileManager, null, null, null, jfiles).call();

        // Creating an instance of our compiled class and
        // running its toString() method
        Class<?> aClass;
        try {
            aClass = fileManager.getClassLoader(null).loadClass(sourceFilename);
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            aClass = null;
        }
        return aClass;
    }
}

